package com.wfm.files;

import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;
import java.nio.file.Path;
import java.nio.file.StandardOpenOption;
import java.util.ArrayList;
import java.util.List;

public class Demo {
    public static void main(String[] args) throws IOException {
        List<FileProcessor.LineInfo> lineInfos = readLineInfos1(Path.of("demo.txt"));
        System.out.println(lineInfos.toString());
    }
    private static List<FileProcessor.LineInfo> readLineInfos(Path inputPath) throws IOException {
        List<FileProcessor.LineInfo> lines = new ArrayList<>();
        try (FileChannel channel = FileChannel.open(inputPath, StandardOpenOption.READ)) {
            ByteBuffer buffer = ByteBuffer.allocate(5);
            long filePosition = 0;
            int lineStart = 0;

            while (channel.read(buffer) != -1) {
                buffer.flip();
                for (int i = 0; i < buffer.limit(); i++) {
                    if (buffer.get(i) == '\n') {
                        int lineLength = i - lineStart + 1;
                        lines.add(new FileProcessor.LineInfo(filePosition + lineStart, lineLength));
                        lineStart = i + 1;
                    }
                }
                filePosition += buffer.limit();
                if (lineStart >= buffer.limit()) {
                    buffer.clear();
                } else {
                    buffer.compact();
                    lineStart = 0;
                }
            }
        }
        return lines;
    }
    private static List<FileProcessor.LineInfo> readLineInfos1(Path inputPath) throws IOException {
        List<FileProcessor.LineInfo> lines = new ArrayList<>();
        try (FileChannel channel = FileChannel.open(inputPath, StandardOpenOption.READ)) {
            ByteBuffer buffer = ByteBuffer.allocate(8192);
            long filePosition = 0;
            int lineStartInBuffer = 0;
            boolean hasRemaining = false;

            while (channel.read(buffer) != -1 || hasRemaining) {
                buffer.flip();

                // 合并上次剩余数据和新数据
                byte[] combined = new byte[buffer.remaining()];
                buffer.get(combined);
                buffer.clear();
                buffer.put(combined);
                buffer.flip();

                for (int i = 0; i < buffer.limit(); i++) {
                    if (buffer.get(i) == '\n') {
                        // 计算绝对起始位置
                        long lineStart = filePosition + lineStartInBuffer;
                        int lineLength = i - lineStartInBuffer + 1;

                        lines.add(new FileProcessor.LineInfo(lineStart, lineLength));

                        // 更新下一行的起始位置
                        lineStartInBuffer = i + 1;
                    }
                }

                // 处理剩余未完成的行
                if (buffer.limit() > 0) {
                    hasRemaining = buffer.get(buffer.limit() - 1) != '\n';
                    filePosition += lineStartInBuffer;

                    // 保存未处理的数据
                    byte[] remaining = new byte[buffer.limit() - lineStartInBuffer];
                    buffer.position(lineStartInBuffer);
                    buffer.get(remaining);

                    buffer.clear();
                    buffer.put(remaining);
                    lineStartInBuffer = 0;
                } else {
                    buffer.clear();
                }
            }

            // 处理最后一行没有换行符的情况
            if (lineStartInBuffer > 0) {
                lines.add(new FileProcessor.LineInfo(filePosition, buffer.limit() - lineStartInBuffer));
            }
        }
        return lines;
    }
}
